package com.semidata.trp.business.report;

import java.io.File;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

import org.apache.ibatis.session.SqlSession;

import com.semidata.rtd.core.log.Logger;
import com.semidata.rtd.core.service.SendableService;
import com.semidata.trp.business.config.Config;
import com.semidata.trp.business.mapper.BusinessMapper;
import com.semidata.trp.business.model.KeyWordModel;
import com.semidata.trp.business.utils.SessionUtils;
import com.semidata.trp.business.utils.Utils;

public class ReportService implements SendableService<MonitorReportData> {

    private static final Config config = Config.getConfig();

    private File baseFile;
    private File currentFile;
    private AtomicReference<ReportData> baseData = new AtomicReference<>();
    private AtomicReference<ReportData> currentData = new AtomicReference<>();
    private Map<String,KeyWordModel> key1 = new HashMap<>();
    private Map<String,Map<String,KeyWordModel>> key2 = new HashMap<>();
    private Map<Integer,Map<String,KeyWordModel>> key3 = new HashMap<>();
    private KeyWordData keyData = new KeyWordData();
    private Thread thread;
    private boolean quit = false;
    private static int SLEEP_TIME = 100;
    private LinkedBlockingQueue<MonitorReportData> queue = new LinkedBlockingQueue<>();

    @Override
    public void start() {
        File reportDataDir = new File(config.getReportDataDir());
        if (reportDataDir.exists()) {
            if (!reportDataDir.isDirectory() || !reportDataDir.canWrite() || !reportDataDir.canRead())
                throw new RuntimeException("report data dir is invalid: " + config.getReportDataDir());
        } else {
            if (!reportDataDir.mkdirs()) {
                throw new RuntimeException("can not create report data dir " + config.getReportDataDir());
            }
        }

        baseFile = new File(reportDataDir, "base.data");
        currentFile = new File(reportDataDir, "current.data");

        baseData.set(loadData(baseFile));
        currentData.set(loadData(currentFile));
        keyData.getKeywords(key1,key2,key3);
        thread = new Thread(new Runnable() {
        	
            @Override
            public void run() {

                while (true) {
                    try {
                        MonitorReportData data = queue.poll(SLEEP_TIME, TimeUnit.MILLISECONDS);
                        if (Utils.getDate(currentData.get().getTime()) != Utils.getDate(baseData.get().getTime())) {
                        	
                            ReportData base = currentData.get().clone();
                            base.dump(baseFile);
                            baseData.set(base);
                        }

                        if (data == null && quit) {
                            break;
                        } else if (data != null) {
                            currentData.get().putMonitorReportData(data);
                            currentData.get().getMonitorReportData();
                            currentData.get().dump(currentFile);
                            keyData.checkAndAddKey(key1,key2,key3,data.getKeyWords());
                        }
                        
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }

        });

        thread.start();

    }

    @Override
    public void stop() {
        quit = true;

        try {
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        currentData.get().dump(currentFile);
    }

    @Override
    public void send(MonitorReportData data) {
    	if (queue.size() == 0)
    		queue.add(data);

    }
    
    private ReportData loadData(File file) {

        if (file.exists()) {
            return new ReportData(file);
        } else {
            ReportData data = new ReportData();
            data.dump(file);
            return data;
        }
    }

    public ReportData getCurrentData() {
        return currentData.get();
    }

    public ReportData getBaseData() {
        return baseData.get();
    }
    
    

}
